package com.corpgovernment.organization.controller.expressaddress;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.corpgovernment.api.organization.dto.request.QueryExpressAddressRequestDto;
import com.corpgovernment.api.organization.model.enums.ExpressAddressProductTypeEnum;
import com.corpgovernment.api.organization.model.expressaddress.ExpressAddressVo;
import com.corpgovernment.api.organization.model.expressaddress.SearchExpressAddressPageRequestVO;
import com.corpgovernment.api.organization.model.expressaddress.SearchExpressAddressResponseVO;
import com.corpgovernment.api.organization.model.expressaddress.UserAddressVo;
import com.corpgovernment.api.organization.utils.RegularUtils;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.ctrip.corp.obt.generic.core.context.UserInfoContext;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.corpgovernment.organization.constant.OrganizationConst;
import com.corpgovernment.organization.entity.db.MbExpressAddress;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.enumm.CorpPayTypeEnum;
import com.corpgovernment.organization.processor.QueryExpressAddressProcessor;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.organization.service.impl.ExpressAddressListServiceImpl;
import com.corpgovernment.organization.service.impl.ExpressAddressServiceImpl;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author  wangyujue
 */
@RestController
@RequestMapping("/expressAddress")
@Slf4j
public class ExpressAddressController {

    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private ExpressAddressServiceImpl expressAddressService;
    @Autowired
    private QueryExpressAddressProcessor queryExpressAddressProcessor;
	@Autowired
    private ExpressAddressListServiceImpl expressAddressListService;

    /**
     * 根据uid获取快递地址，当前只有flight产线，先根据部门查，查不到网上找，直到找到为止
     *
     * @param uid 用户id
     * @return ExpressAddressVo
     */
    @RequestMapping("/findExpressAddress")
    public JSONResult<ExpressAddressVo> findExpressAddress(@RequestParam(value = "uid") String uid,
                                     @RequestParam(value = "orgId") String orgId,
                                     @RequestParam(value = "expressAddressProductTypeEnum") ExpressAddressProductTypeEnum expressAddressProductTypeEnum,
                                     @RequestParam(value = "corpPayType") String corpPayType) {
        log.info("获取配送地址uid[{}],expressAddressProductTypeEnum[{}],corpPayType[{}]", uid, expressAddressProductTypeEnum, corpPayType);
        ExpressAddressVo expressAddressVo = new ExpressAddressVo();
        // #1.因公，查询当前部门的默认配送地址，如果没有，返回一条最新的。如果部门没有配置，则按同样规则查找子公司的，最后再没有返回空
        if (corpPayType.equals(CorpPayTypeEnum.PUB.toString())) {
            return findPubAddress(orgId, expressAddressVo);
        }
        // #2.因私，查询个人的默认地址，没有返回个人最近的地址
        if (corpPayType.equals(CorpPayTypeEnum.OWN.toString())) {
            return findOwnAddress(uid, expressAddressVo);
        }
        return new JSONResult<>(null);
    }

    private JSONResult<ExpressAddressVo> findOwnAddress(String uid, ExpressAddressVo expressAddressVo) {
        List<MbExpressAddress> expressAddressList = expressAddressService.listByUid(uid, null, null, null);
        if (CollUtil.isNotEmpty(expressAddressList)) {
            List<MbExpressAddress> defaultAddressList = expressAddressList.stream().filter(p -> p.getIsDefault() != null).filter(MbExpressAddress::getIsDefault).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(defaultAddressList)) {
                MbExpressAddress expressAddress = defaultAddressList.get(0);
                BeanUtil.copyProperties(expressAddress, expressAddressVo);
                return new JSONResult<>(expressAddressVo);
            }
            MbExpressAddress expressAddress = expressAddressList.stream().max(Comparator.comparing(MbExpressAddress::getDatachangeCreatetime)).orElse(null);
            if (expressAddress == null) {
                return new JSONResult<>(null);
            }
            BeanUtil.copyProperties(expressAddress, expressAddressVo);
            return new JSONResult<>(expressAddressVo);
        } else {
            return new JSONResult<>(null);
        }
    }

    private JSONResult<ExpressAddressVo> findPubAddress(@RequestParam("orgId") String orgId, ExpressAddressVo expressAddressVo) {
        MbExpressAddress currentExpressAddress = new MbExpressAddress();
        // 查询当前组织架构list的地址
        List<MbExpressAddress> expressAddressList = expressAddressService.listByOrgId(orgId);
        // 当前组织没有，查找最近公司
        if (CollUtil.isEmpty(expressAddressList)) {
            MbOrgInfo recentCompanyInfo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
            List<MbExpressAddress> companyExpressAddressList = expressAddressService.listByOrgId(recentCompanyInfo.getOrgId());
            // 如果公司也没有，直接返回空
            if (CollUtil.isEmpty(companyExpressAddressList)) {
                return new JSONResult<>(null);
            }
            List<MbExpressAddress> defaultAddressList = companyExpressAddressList.stream().filter(p -> p.getIsDefault() != null).filter(MbExpressAddress::getIsDefault).collect(Collectors.toList());
            // 有默认的返回默认的
            if (CollUtil.isNotEmpty(defaultAddressList)) {
                MbExpressAddress expressAddress = defaultAddressList.get(0);
                BeanUtil.copyProperties(expressAddress, expressAddressVo);
                return new JSONResult<>(expressAddressVo);
            }
            currentExpressAddress = expressAddressList.stream().max(Comparator.comparing(MbExpressAddress::getDatachangeCreatetime)).orElse(null);
            BeanUtil.copyProperties(currentExpressAddress, expressAddressVo);
            return new JSONResult<>(expressAddressVo);
        }
        // 用户所属部门的配送地址信息
        List<MbExpressAddress> defaultAddressList = expressAddressList.stream().filter(p -> p.getIsDefault() != null).filter(MbExpressAddress::getIsDefault).collect(Collectors.toList());
        if (CollUtil.isEmpty(defaultAddressList)) {
            currentExpressAddress = expressAddressList.stream().max(Comparator.comparing(MbExpressAddress::getDatachangeCreatetime)).orElse(null);
        } else {
            currentExpressAddress = defaultAddressList.get(0);
        }
        if (currentExpressAddress == null) {
            return new JSONResult<>(null);
        }
        BeanUtil.copyProperties(currentExpressAddress, expressAddressVo);
        return new JSONResult<>(expressAddressVo);
    }



    /**
     * 根据uid获取快递地址，当前只有flight产线，先根据部门查，查不到网上找，直到找到为止
     *
     * @param uid 用户id
     * @return ExpressAddressVo
     */
    @RequestMapping("/getExpressAddress")
    public JSONResult<List<ExpressAddressVo>> getExpressAddress(@RequestParam(value = "uid") String uid,
                                                    @RequestParam(value = "orgId") String orgId,
                                                    @RequestParam(value = "expressAddressProductTypeEnum") ExpressAddressProductTypeEnum expressAddressProductTypeEnum,
                                                    @RequestParam(value = "corpPayType") String corpPayType) {
        log.info("获取配送地址uid[{}],expressAddressProductTypeEnum[{}],corpPayType[{}]", uid, expressAddressProductTypeEnum, corpPayType);

        // #1.因公，查询当前部门的默认配送地址，如果没有，返回一条最新的。如果部门没有配置，则按同样规则查找子公司的，最后再没有返回空
        if (corpPayType.equals(CorpPayTypeEnum.PUB.toString())) {
            return companyAddress(orgId,uid);
        }
        // #2.因私，查询个人的默认地址，没有返回个人最近的地址
        if (corpPayType.equals(CorpPayTypeEnum.OWN.toString())) {
            return personalAddress(uid);
        }
        return JSONResult.success(Lists.newArrayList());
    }

    private JSONResult<List<ExpressAddressVo>> personalAddress(String uid) {
        List<MbExpressAddress> expressAddressList = expressAddressService.listByUid(uid, null, null, null);
        List<ExpressAddressVo> lists = Lists.newArrayList();
        if (CollUtil.isNotEmpty(expressAddressList)) {
            List<MbExpressAddress> defaultAddressList = expressAddressList.stream().filter(p -> p.getIsDefault() != null).filter(MbExpressAddress::getIsDefault).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(defaultAddressList)) {
                MbExpressAddress expressAddress = defaultAddressList.get(0);
                ExpressAddressVo expressAddressVo = JsonUtils.convert(expressAddress, ExpressAddressVo.class);
                expressAddressVo.setRecipientMobilePhone(expressAddress.getRecipientPhone());
                lists.add(expressAddressVo);
                return JSONResult.success(lists);
            }
            MbExpressAddress expressAddress = expressAddressList.stream().max(Comparator.comparing(MbExpressAddress::getDatachangeCreatetime)).orElse(null);
            if (expressAddress == null) {
                return JSONResult.success(lists);
            }
            ExpressAddressVo expressAddressVo = JsonUtils.convert(expressAddress, ExpressAddressVo.class);
            expressAddressVo.setRecipientMobilePhone(expressAddress.getRecipientPhone());
            if(expressAddressVo != null){
                lists.add(expressAddressVo);
            }
        }
        return JSONResult.success(lists);
    }

    private JSONResult<List<ExpressAddressVo>> companyAddress(@RequestParam("orgId") String orgId,@RequestParam("uid") String uid) {
        // 查询当前组织架构list的地址
        MbExpressAddress currentExpressAddress = new MbExpressAddress();
        List<MbExpressAddress> expressAddressList = expressAddressService.listByOrgId(orgId);
        // 当前组织没有，查找最近公司
        List<ExpressAddressVo> lists = Lists.newArrayList();
        if (CollUtil.isEmpty(expressAddressList)) {
            MbOrgInfo recentCompanyInfo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
            List<MbExpressAddress> companyExpressAddressList = expressAddressService.listByOrgId(recentCompanyInfo.getOrgId());
            // 如果公司也没有，直接返回空
            if (CollUtil.isEmpty(companyExpressAddressList)) {
                return JSONResult.success(lists);
            }
            List<MbExpressAddress> defaultAddressList = companyExpressAddressList.stream().filter(p -> p.getIsDefault() != null).filter(MbExpressAddress::getIsDefault).collect(Collectors.toList());
            // 有默认的返回默认的
            if (CollUtil.isNotEmpty(defaultAddressList)) {
                MbExpressAddress expressAddress = defaultAddressList.get(0);
                ExpressAddressVo expressAddressVo = JsonUtils.convert(expressAddress, ExpressAddressVo.class);
                expressAddressVo.setRecipientMobilePhone(expressAddress.getRecipientPhone());
                if(expressAddressVo != null){
                    lists.add(expressAddressVo);
                }
                JSONResult<List<ExpressAddressVo>> listJSONResult = personalAddress(uid);
                if(listJSONResult != null && !CollectionUtils.isEmpty(listJSONResult.getData()) && listJSONResult.isSUCCESS()){
                    List<ExpressAddressVo> personal = listJSONResult.getData();
                    lists.add(personal.get(0));
                }
                return JSONResult.success(lists);
            }
            currentExpressAddress = companyExpressAddressList.stream().max(Comparator.comparing(MbExpressAddress::getDatachangeCreatetime)).orElse(null);
            ExpressAddressVo expressAddressVo = JsonUtils.convert(currentExpressAddress, ExpressAddressVo.class);
            expressAddressVo.setRecipientMobilePhone(currentExpressAddress.getRecipientPhone());
            if(expressAddressVo != null){
                lists.add(expressAddressVo);
            }
            JSONResult<List<ExpressAddressVo>> listJSONResult = personalAddress(uid);
            if(listJSONResult != null && !CollectionUtils.isEmpty(listJSONResult.getData()) && listJSONResult.isSUCCESS()){
                List<ExpressAddressVo> personal = listJSONResult.getData();
                lists.add(personal.get(0));
            }
            return JSONResult.success(lists);
        }
        // 用户所属部门的配送地址信息
        List<MbExpressAddress> defaultAddressList = expressAddressList.stream().filter(p -> p.getIsDefault() != null).filter(MbExpressAddress::getIsDefault).collect(Collectors.toList());
        if (CollUtil.isEmpty(defaultAddressList)) {
            currentExpressAddress = expressAddressList.stream().max(Comparator.comparing(MbExpressAddress::getDatachangeCreatetime)).orElse(null);
        } else {
            currentExpressAddress = defaultAddressList.get(0);
        }
        if (currentExpressAddress == null) {
            return JSONResult.success(lists);
        }
        ExpressAddressVo expressAddressVo = JsonUtils.convert(currentExpressAddress, ExpressAddressVo.class);
        expressAddressVo.setRecipientMobilePhone(currentExpressAddress.getRecipientPhone());
        if(expressAddressVo != null){
            lists.add(expressAddressVo);
        }
        JSONResult<List<ExpressAddressVo>> listJSONResult = personalAddress(uid);
        if(listJSONResult != null && !CollectionUtils.isEmpty(listJSONResult.getData()) && listJSONResult.isSUCCESS()){
            List<ExpressAddressVo> personal = listJSONResult.getData();
            lists.add(personal.get(0));
        }

        return JSONResult.success(lists);
    }

    /**
     * 查询用户的地址
     *
     * @param deliveryListRequest
     * @return
     */
//    @RequestMapping("/listByUid")
//    @Deprecated
//    public JSONResult<DeliveryListResponse> listByUid(BaseUserInfo userInfo, @RequestBody @Valid DeliveryListRequest deliveryListRequest) {
//        deliveryListRequest.setOrgId(userInfo.getOrgId());
//        return expressAddressListService.expressAddressList(deliveryListRequest);
//    }

    /**
     * 查询用户的地址
     *
     * @param request
     * @return
     */
    @RequestMapping("/expressAddressList")
    public JSONResult<SearchExpressAddressResponseVO> queryExpressAddressList(@RequestBody SearchExpressAddressPageRequestVO request, BaseUserInfo baseUserInfo) {
        request.setBaseUserInfo(baseUserInfo);
		return JSONResult.success(expressAddressListService.queryExpressAddressList(request));
    }

    /**
     * 根据uid获取快递地址，当前只有flight产线，先根据部门查，查不到网上找，直到末级子公司, 没有找到返回null
     */
    @RequestMapping("/queryExpressAddress")
    public JSONResult<ExpressAddressVo> queryExpressAddress(@RequestBody QueryExpressAddressRequestDto request) {
        return queryExpressAddressProcessor.process(request);
    }

    /**
     * 添加用户地址
     *
     * @param userAddressVo
     * @return
     */
    @RequestMapping("/addUserAddress")
    public JSONResult<Boolean> addUserAddress(@RequestBody UserAddressVo userAddressVo, BaseUserInfo baseUserInfo) {
        userAddressVo.setUid(baseUserInfo.getUid());
        userAddressVo.setOrgId(baseUserInfo.getOrgId());
        log.info("添加用户地址开始[{}]", JsonUtils.toJsonString(userAddressVo));
        MbExpressAddress model = expressAddressListService.convertAddExpressAddress(userAddressVo);
        if (model != null && model.getIsDefault()) {//查询当前组织下其他默认地址为true
            List<MbExpressAddress> expressAddresses = expressAddressService.listByOrgIdAndDefaultAddress(model.getOrgId(),true);
            if(!CollectionUtils.isEmpty(expressAddresses)){
                expressAddressService.updateByOrgId(model.getOrgId());//批量更新默认地址
            }
        }
        Boolean flag = expressAddressService.insertExpressAddress(model);
        return new JSONResult<>(flag);
    }

    /**
     * 更新用户地址
     *
     * @param userAddressVo
     * @return
     */
    @RequestMapping("/updateUserAddress")
    public JSONResult<Boolean> updateUserAddress(@RequestBody UserAddressVo userAddressVo) {
        //区分前后端
//        String source = userAddressVo.getDevice();
//        if (!DeviceEnum.PC.toString().equalsIgnoreCase(source)) {
//            //参数验证
//            validateParams(userAddressVo);
//        }
        MbExpressAddress model = expressAddressListService.convertUpdateExpressAddress(userAddressVo);

        if (model != null && model.getIsDefault()) {
            List<MbExpressAddress> expressAddresses = expressAddressService.listByOrgIdAndDefaultAddress(model.getOrgId(),true);
            if(!CollectionUtils.isEmpty(expressAddresses)){
                expressAddressService.updateByOrgId(model.getOrgId());//批量更新默认地址
            }
        }
        Boolean flag = expressAddressService.updateUserAddress(model);
        return new JSONResult<>(flag);
    }

    /**
     * 删除用户地址
     *
     * @param userAddressVo
     * @return
     */
    @RequestMapping("/deleteUserAddress")
    public JSONResult<Boolean> deleteUserAddress(@RequestBody UserAddressVo userAddressVo) {
        Optional.ofNullable(UserInfoContext.getContextParams(BaseUserInfo.class))
            .ifPresent(baseUserInfo -> userAddressVo.setUid(baseUserInfo.getUid()));
        Boolean flag = expressAddressService.deleteUserAddress(userAddressVo);
        return new JSONResult<>(flag);
    }

	/**
	 * 检测用户地址，id不为空更新，id为空新增
	 *
	 * @param userAddressVo 用户地址
	 * @return
	 */
	@RequestMapping("/saveUserAddress")
	public JSONResult<Boolean> saveUserAddress(@RequestBody UserAddressVo userAddressVo, BaseUserInfo baseUserInfo) {
		log.info("checkUserAddress检测用户地址[{}]", JsonUtils.toJsonString(userAddressVo));
		Long id = userAddressVo.getId();
		if (id == null) {
			log.info("检测用户地址走新增逻辑");
			return addUserAddress(userAddressVo, baseUserInfo);
		} else {
			log.info("检测用户地址走更新逻辑");
			return updateUserAddress(userAddressVo);
		}
	}


    /**
     * 从部门开始遍历，一直到最近子公司，找到一个地址就返回，否则返回null
     *
     * @param orgInfoMap
     * @param expressAddressMap
     * @param orgId
     * @param firstFlag
     * @return
     */
    private MbExpressAddress find(Map<String, MbOrgInfo> orgInfoMap, Map<String, MbExpressAddress> expressAddressMap, String orgId, boolean firstFlag) {
        MbExpressAddress expressAddress = expressAddressMap.get(orgId);
        if (expressAddress != null && checkData(expressAddress)) {
            return expressAddress;
        } else {
            MbOrgInfo mbOrgInfo = orgInfoMap.get(orgId);
            if (mbOrgInfo == null) {
                return null;
            }
            // 如果向上没找到，且到了公司级别，直接返回null
            if (mbOrgInfo.getOrgType().equals(OrganizationConst.COMPANY) && !firstFlag) {
                return null;
            }
            // 第一次公司查找要放过，用一个标识控制是否是第一次
            if (mbOrgInfo.getOrgType().equals(OrganizationConst.COMPANY)) {
                firstFlag = false;
            }
            String parentId = mbOrgInfo.getParentId();
            return find(orgInfoMap, expressAddressMap, parentId, firstFlag);
        }
    }

    /**
     * 数据校验
     *
     * @param expressAddress
     * @return
     */
    private boolean checkData(MbExpressAddress expressAddress) {
        String provinceName = expressAddress.getProvinceName();
        String cityName = expressAddress.getCityName();
        String districtName = expressAddress.getDistrictName();
        String address = expressAddress.getAddress();
        String recipientName = expressAddress.getRecipientName();
        String recipientMobilePhone = expressAddress.getRecipientPhone();
        String postCode = expressAddress.getPostCode();
        if (StringUtils.isBlank(provinceName) &&
                StringUtils.isBlank(cityName) &&
                StringUtils.isBlank(districtName) &&
                StringUtils.isBlank(address) &&
                StringUtils.isBlank(recipientName) &&
                StringUtils.isBlank(recipientMobilePhone)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * pc端新增，修改参数校验
     *
     * @param userAddressVo
     */
    void validateParams(UserAddressVo userAddressVo) {
        String recipientName = userAddressVo.getRecipientName();//收件人姓名
        if (StringUtils.isBlank(recipientName)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.RECIPIENT_NAME_IS_NULL);
		}
        String provinceName = userAddressVo.getProvinceName();//省
		if (StringUtils.isBlank(provinceName)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.PROVINCE_NAME_IS_NULL);
		}
        String cityName = userAddressVo.getCityName();//市
		if (StringUtils.isBlank(cityName)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.CITY_IS_NULL);
		}
        String districtName = userAddressVo.getDistrictName();//地区
		if (StringUtils.isBlank(districtName)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.DISTRICT_NAME_IS_NULL);
		}
        String address = userAddressVo.getAddress();//详细地址
		if (StringUtils.isBlank(address)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.ADDRESS_IS_NULL);
		}
        String postCode = userAddressVo.getPostCode();//邮编
		if (StringUtils.isNotBlank(postCode) && !RegularUtils.isPostCode(postCode)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.CONTRACT_EMAIL_FORMAT_ERROR);
		}
        String recipientMobilePhone = userAddressVo.getRecipientMobilePhone();//手机号
		if (StringUtils.isBlank(recipientMobilePhone)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
		}
    }
}
